# -*-coding: utf-8 -*-
"""
    @Theme   : Suzy Blog
    @Time    : 2024/4/10 13:02
    @Author  : YamFish
    @Url     : https://www.zhihu.com/people/yamfish
"""
import os

import click
from flask import Flask, render_template
from flask_login import current_user
from flask_wtf.csrf import CSRFError

from suzyblog.blueprints.auth import auth_bp
from suzyblog.blueprints.admin import admin_bp
from suzyblog.blueprints.blog import blog_bp
from suzyblog.models import Admin, Category, Post, Comment, Link
from suzyblog.settings import config
from suzyblog.extensions import mail, moment, db, ck_editor, bootstrap, login_manager, csrf


def make_app(config_name=None):
    if config_name is None:
        config_name = os.getenv('FLASK_CONFIG', 'development')

    app = Flask(__name__)
    app.config.from_object(config[config_name])

    register_errors(app)
    register_cli(app)
    register_extensions(app)
    register_blueprints(app)
    register_shell_context(app)
    register_template_context(app)
    register_log(app)

    return app


def register_errors(app):
    @app.errorhandler(400)
    def bad_request(e):
        return render_template('errors/400.html'), 400

    @app.errorhandler(404)
    def page_not_found(e):
        return render_template('errors/404.html'), 404

    @app.errorhandler(500)
    def internal_server_error(e):
        return render_template('errors/500.html'), 500

    @app.errorhandler(CSRFError)
    def csrf_error(e):
        return render_template('errors/400.html', description=e.description), 400


def register_cli(app):
    @app.cli.command()
    @click.option('--drop', is_flag=True, help='Drop tables and then create all')
    def init_db(drop):
        """init database"""
        if drop:
            click.confirm('This operation will drop all tables, continue?', abort=True)
            db.drop_all()
            click.echo('Tables have been dropped ok.')
        db.create_all()
        click.echo('Initialize databases OK!')

    @app.cli.command()
    @click.option('--category', default=10, help='The nums of category, default is 10.')
    @click.option('--post', default=50, help='The nums of post, default is 50.')
    @click.option('--comment', default=500, help='The nums of comment, default is 100.')
    def forge(category, post, comment):
        """Generate fake date"""
        from suzyblog.fakes import admin_faker, categories_faker, posts_faker, comments_faker, links_faker

        db.drop_all()
        db.create_all()

        click.echo('Generating admin user...')
        admin_faker()

        click.echo(f'Generating {category} categories...')
        categories_faker(category)

        click.echo(f'Generating {post} posts...')
        posts_faker(post)

        click.echo(f'Generating {comment} comments...')
        comments_faker(comment)

        click.echo('Generating Links...')
        links_faker()

        click.echo('Generating forge data OK!')

    @app.cli.command()
    @click.option('--username', prompt=True, help='login user name')
    @click.option('--password', prompt=True, hide_input=True, confirmation_prompt=True, help='login user password')
    def init_admin(username, password):
        """init admin and Default Category"""
        admin = Admin.query.first()
        if admin:
            click.echo('Admin user already exists, updating...')
            admin.username = username
            admin.password = password
        else:
            click.echo('Create Temporary Account for Admin user...')
            admin = Admin(username=username, blog_title='Suzy Blog', blog_sub_title="To Make Each Day Count",
                          name='Admin', about='Anything about you.')
            admin.password = password
            db.session.add(admin)

        category = Category.query.first()
        if category is None:
            click.echo('Generate the Default Category...')
            category = Category(name='Default')
            db.session.add(category)

        db.session.commit()
        click.echo('Init admin account OK!')


def register_extensions(app):
    mail.init_app(app)
    db.init_app(app)
    moment.init_app(app)
    ck_editor.init_app(app)
    bootstrap.init_app(app)
    login_manager.init_app(app)
    csrf.init_app(app)


def register_blueprints(app):
    app.register_blueprint(auth_bp, url_prefix='/auth')
    app.register_blueprint(admin_bp, url_prefix='/admin')
    app.register_blueprint(blog_bp)


def register_shell_context(app):
    @app.shell_context_processor
    def shell_context():
        return dict(Admin=Admin, Category=Category, Post=Post, Comment=Comment)


def register_template_context(app):
    @app.context_processor
    def template_context():
        admin = Admin.query.first()
        categories = Category.query.order_by(Category.name).all()
        links = Link.query.order_by(Link.name).all()
        unread_comments = None
        if current_user.is_authenticated:
            unread_comments = Comment.query.filter_by(reviewed=False).count()
        return dict(admin=admin, categories=categories, links=links, unread_comments=unread_comments)


def register_log(app):
    pass

